package scau.zhong.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import scau.zhong.common.user.auth.JwtUtils;
import scau.zhong.config.RsaKeyProperties;
import scau.zhong.pojo.Role;
import scau.zhong.pojo.User;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 重写security的认证规则
 * 签发token
 * JWT过滤器，采用token形式的登录认证
 */

public class JwtTokenFilter extends UsernamePasswordAuthenticationFilter {


    private AuthenticationManager authenticationManager;
    private RsaKeyProperties rsaKeyProperties;
    private final int EXPIRE_TIME=24 * 60;

    public JwtTokenFilter(AuthenticationManager authenticationManager, RsaKeyProperties rsaKeyProperties) {
        this.authenticationManager = authenticationManager;
        this.rsaKeyProperties = rsaKeyProperties;
    }

    /**
     * 用户认证
     * @param request
     * @param response
     * @return
     * @throws AuthenticationException
     */
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        try {
            //从请求中读取json并转为对象
            User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
            System.out.println(user.getRoles());
            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword());
            return this.authenticationManager.authenticate(authRequest);
        } catch (Exception e) {
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); //401异常
            try {
                PrintWriter writer = response.getWriter();
                Map resultMap = new HashMap();
                resultMap.put("code",HttpServletResponse.SC_UNAUTHORIZED);
                resultMap.put("msg","用户名或密码错误");
                writer.write(new ObjectMapper().writeValueAsString(resultMap));
                writer.flush();
                writer.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            throw new RuntimeException();
        }
    }

    /**
     * 认证成功回调，返回用户一个token
     * @param request
     * @param response
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     */
    public void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        User user = new User();
        //不要放入密码到Token中，有可能会泄露的
        user.setUsername(authResult.getName());
        user.setRoles((List<Role>) authResult.getAuthorities());
        //System.out.println(authResult.getAuthorities());
        String token = JwtUtils.generateTokenExpireInMinutes(user, rsaKeyProperties.getPrivateKey(), EXPIRE_TIME);// 一天过期
        //写入到请求头
        response.addHeader("Authorization","Zhong "+token);
        //写入成功信息
        response.setContentType("application/json;charset=utf-8");
        response.setStatus(HttpServletResponse.SC_OK); //401异常
        try {
            PrintWriter writer = response.getWriter();
            Map resultMap = new HashMap();
            resultMap.put("code",HttpServletResponse.SC_OK);
            resultMap.put("msg","认证通过");
            writer.write(new ObjectMapper().writeValueAsString(resultMap));
            writer.flush();
            writer.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }
}
